package com.zz.admin.common.aspect;

import cn.hutool.core.util.ReflectUtil;
import com.zz.common.utils.convert.LocalDateTimeUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Map;

/**
 * @author zl
 * @version 1.0
 */
@Aspect
@Component
public class DataDealAspect {

    @Pointcut("execution(public * com..BaseMapper.insert(..))")
    public void insert() {
    }

    @Pointcut("execution(public * com..BaseMapper.updateById(..))")
    public void updateById() {
    }

    @Before("insert()")
    public void beforeInsert(JoinPoint joinPoint) {
        LocalDateTime date = LocalDateTimeUtil.now();

        Object arg = joinPoint.getArgs()[0];

        if (arg == null) {
            return;
        }

        if (arg instanceof Collection) {
            // 批量插入的情况
            Collection<?> collection = (Collection<?>) arg;
            for (Object item : collection) {
                if (item != null) {
                    setDates(item, date);
                }
            }
        } else {
            // 单条插入的情况
            setDates(arg, date);
        }
    }

    private void setDates(Object obj, LocalDateTime date) {
        if (obj instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) obj;
            if (map.containsKey("create_date")) {
                map.put("create_date", date);
            } else if (map.containsKey("createDate")) {
                map.put("createDate", date);
            }
            if (map.containsKey("update_date")) {
                map.put("update_date", date);
            } else if (map.containsKey("updateDate")) {
                map.put("updateDate", date);
            }
        } else {
            Method method = ReflectUtil.getMethod(obj.getClass(), "setCreateDate", LocalDateTime.class);
            if (method != null) {
                ReflectUtil.invoke(obj, method, date);
            }
            method = ReflectUtil.getMethod(obj.getClass(), "setUpdateDate", LocalDateTime.class);
            if (method != null) {
                ReflectUtil.invoke(obj, method, date);
            }
        }

    }

    @Before("updateById()")
    public void beforeUpdate(JoinPoint joinPoint) {
        LocalDateTime date = LocalDateTimeUtil.now();

        Object arg = joinPoint.getArgs()[0];
        if (arg == null) {
            return;
        }

        if (arg instanceof Collection) {
            // 批量更新的情况
            Collection<?> collection = (Collection<?>) arg;
            for (Object item : collection) {
                if (item != null) {
                    setUpdateDate(item, date);
                }
            }
        } else {
            // 单条更新的情况
            setUpdateDate(arg, date);
        }
    }

    private void setUpdateDate(Object obj, LocalDateTime date) {
        Method method = ReflectUtil.getMethod(obj.getClass(), "setUpdateDate", LocalDateTime.class);
        if (method != null) {
            ReflectUtil.invoke(obj, method, date);
        }
    }
}
